#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "p2p-file.h"
#include "p2p-peer.h"
#include "p2p-config.h"
#include "utils.h"

peer_t *init_peer(int psfd)
{
    peer_t *peer_head = (peer_t *)malloc(sizeof(peer_t));

    peer_head->psfd = psfd;
    peer_head->state = INIT;
    peer_head->data_exchange = 0;
    peer_head->data_pending = 0;
    peer_head->piece_head = NULL;
    peer_head->piece = NULL;
    peer_head->piece_tail = NULL;
    peer_head->piece_count = 0;
    peer_head->piece_map = NULL;
    peer_head->prev = NULL;
    peer_head->next = NULL;
    
    return peer_head;
}

peer_t *add_peer(peer_t *peer_tail, int psfd)
{
    peer_t *temp = (peer_t *)malloc(sizeof(peer_t));
    
    assert(peer_tail->next == NULL);

    temp->psfd = psfd;
    temp->state = INIT;
    temp->data_exchange = 0;
    temp->data_pending = 0;
    temp->piece_head = NULL;
    temp->piece = NULL;
    temp->piece_tail = NULL;
    temp->piece_count = 0;
    temp->piece_map = NULL;
    temp->next = NULL;
    temp->prev = peer_tail;
    peer_tail->next = temp;
    
    return temp;
}

int del_peer(peer_t **peer_head, peer_t **peer_tail, peer_t *peer)
{
    assert((*peer_head)->prev == NULL);
    assert((*peer_tail)->next == NULL);
   
    if (peer == *peer_head) {
        *peer_head = peer->next;
        // If there is not just one peer
        if (peer->next != NULL)
            peer->next->prev = NULL;
    } else if (peer == *peer_tail) {
        *peer_tail = peer->prev;
        // If there is not just one peer
        if (peer->prev != NULL)
            peer->prev->next = NULL;
    } else {
        peer->prev->next = peer->next;
        peer->next->prev = peer->prev;
    }

    if (peer->piece_map != NULL)
        free(peer->piece_map);
    del_piece_all(&(peer->piece_head));

    free(peer);
    return 0;
}

peer_t *search_peer(peer_t *peer_head, int psfd)
{
    peer_t *peer = peer_head;

    assert(peer_head != NULL);

    do {
        if (peer->psfd == psfd)
            return peer;
        peer = peer->next;
    } while (peer != NULL);

    return NULL;
}

